/*!
\copyright  Copyright (c) 2024 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file       streaming_statistics.c
\brief      Streaming Statistics implementation
*/

#include "streaming_statistics.h"
#include "audio_info.h"
#include "audio_sources.h"
#include "context_framework.h"
#include "context_types.h"
#include "handset_service.h"
#include "kymera_adaptation_audio_protected.h"
#include "streaming_statistics_reader.h"
#include "streaming_statistics_utils.h"
#include <logging.h>
#include <panic.h>
#include <vm.h>
#include "device_properties.h"
#include "mirror_profile.h"

static bool streamingStatistics_GetLeaStatistics(context_streaming_info_t *streaming_stats, uint8_t codec_type)
{
    bool status = FALSE;
    streaming_stats->type = CONTEXT_STREAMING_STATISTICS_TYPE_LEA;
    streaming_stats->u.lea.codec_type = codec_type;

    int16_t rssi = 0;
    status |= StreamingStatistics_GetCisRssi(&rssi);

    streaming_stats->common.primary_rssi = rssi;

    switch(codec_type)
    {
        case KYMERA_LE_AUDIO_CODEC_LC3:
        {
            status |= StreamingStatistics_ReadLc3StreamingStatistics(streaming_stats);
            break;
        }
        case KYMERA_LE_AUDIO_CODEC_APTX_ADAPTIVE:
        {
            status |= StreamingStatistics_ReadLeaAptxAdaptiveStreamingStatistics(streaming_stats);
            break;
        }
        case KYMERA_LE_AUDIO_CODEC_APTX_LITE:
        case KYMERA_LE_AUDIO_CODEC_APTX_ADAPTIVE_R4:
        default:
            return FALSE;
    }

    return status;
}

static bool streamingStatistics_GetA2dpStatistics(context_streaming_info_t *streaming_stats, uint8_t seid)
{
    bool status = FALSE;
    streaming_stats->type = CONTEXT_STREAMING_STATISTICS_TYPE_A2DP;
    streaming_stats->u.a2dp.seid = seid;
    streaming_stats->common.is_adaptive = StreamingStatistics_IsA2dpAdaptive(seid);
    streaming_stats->common.is_lossless = streaming_stats->common.is_adaptive && StreamingStatistics_IsA2dpLossless();

    uint16_t link_quality = 0;
    tp_bdaddr addr = {0};
    int16_t rssi = 0;

    /* Ensure to get the device address associated to the routed source */
    generic_source_t source = AudioInfo_GetRoutedGenericSource();
    PanicFalse(GenericSource_IsValid(source));
    PanicFalse(GenericSource_IsAudio(source));
    if (StreamingStatistics_GetTpAddressFromAudioSource(source.u.audio, &addr))
    {
        status |= VmBdAddrGetRssi(&addr, &rssi);
        status |= VmGetAclLinkQuality(&addr, &link_quality);
    }

    streaming_stats->common.primary_rssi = rssi;
    streaming_stats->u.a2dp.primary_link_quality = link_quality;

    uint32_t bitrate = 0;
    status |= StreamingStatistics_ReadA2dpBitrate(&bitrate);
    streaming_stats->common.bitrate = bitrate;

    memset(&streaming_stats->u.a2dp.ttp_histogram, 0xFF, sizeof(audio_a2dp_ttp_toa_delta_histogram_t));
    status |= StreamingStatistics_ReadTtpHistogram(&streaming_stats->u.a2dp.ttp_histogram);
    
    streaming_stats->u.a2dp.seqn_errors = 0xFFFFFFFF;
    status |= StreamingStatistics_ReadSeqnErrors(&streaming_stats->u.a2dp.seqn_errors);

    return status;
}


static bool streamingStatistics_GetStreamingStatistics(unsigned *context_data, uint8 context_data_size)
{
    PanicZero(context_data_size >= sizeof(context_streaming_info_t));
    memset(context_data, 0, sizeof(context_streaming_info_t));

    context_streaming_info_t *streaming_stats = (context_streaming_info_t *) context_data;

    generic_source_t source = AudioInfo_GetRoutedGenericSource();

    if(!GenericSource_IsAudio(source))
    {
        DEBUG_LOG_V_VERBOSE("streamingStatistics_GetStreamingStatistics: Source is not audio.");
        return FALSE;
    }

    DEBUG_LOG_V_VERBOSE("streamingStatistics_GetStreamingStatistics: Source: 0x%0x, ", source.u.audio);

    bool status = FALSE;

    source_defined_params_t source_params;
    if(!AudioSources_GetConnectParameters(source.u.audio, &source_params)
    )
    {
        DEBUG_LOG_VERBOSE("streamingStatistics_GetStreamingStatistics: Could not get connect parameters.");
        return FALSE;
    }

    if(AudioSource_IsLeAudio(source.u.audio) && source_params.data_length == sizeof(le_audio_connect_parameters_t))
    {
        DEBUG_LOG_VERBOSE("streamingStatistics_GetStreamingStatistics: LEA.");
        le_audio_connect_parameters_t *params = source_params.data;
        status =  streamingStatistics_GetLeaStatistics(streaming_stats, params->media.codec_type);
    }

    if(AudioSource_IsA2dp(source.u.audio) && source_params.data_length == sizeof(a2dp_connect_parameters_t))
    {
        a2dp_connect_parameters_t *params = source_params.data;
        DEBUG_LOG_VERBOSE("streamingStatistics_GetStreamingStatistics: A2DP.");
        status = streamingStatistics_GetA2dpStatistics(streaming_stats, params->seid);
    }


    AudioSources_ReleaseConnectParameters(source.u.audio,  &source_params);
    return status;
}

void StreamingStatistics_Init(void)
{
    ContextFramework_RegisterContextProvider(context_streaming_info,
                                             streamingStatistics_GetStreamingStatistics);
}
